home *** CD-ROM | disk | FTP | other *** search
- #include <graphics libraries.h>
- #include <graphics toolbox.h>
- #include "SymmetryUtils.h"
- #include "TileConstants.h"
- #include "TileProtos.h"
- #include "Group2.h"
-
- extern gxPatternRecord gPattern;
- extern gxShape gTileShape;
- extern dragger gDragger; // A record containing a manipulable contour & associated stuff
- extern gxShape gOpShapes[]; // Group of shapes to show the
- // symmetry operations
- extern gxViewPort gViewPort;
-
- extern Boolean gContRedraw, gKeepClosed;
-
- // Prototype of a function in utils.c we use
- long labs(long i);
-
-
- ///////////////////////////////////////////////////////////////////////////////////
- // Group p2
-
- // Test for a hit on an op shape, tracking the drag and returning true
- // if one was hit, false otherwise
- Boolean p2_OpShapeHit(gxPoint *clickPt)
- {
- gxHitTestInfo hitStats;
- gxShape hitShape, oldShape;
- gxTransform xForm;
- long shapeNum;
-
- // Don't check shpe 0
- for(shapeNum = 1; shapeNum < 3; shapeNum++)
- {
- hitShape = gOpShapes[shapeNum];
- xForm = GXGetShapeTransform(hitShape);
-
- // Test for a hit on the startCap
- GXIgnoreGraphicsNotice(attributes_already_set);
- GXSetTransformHitTest(xForm, gxAnyPart, kHitTolerance);
- GXPopGraphicsNotice();
-
- // If shape was hit, we're done looking
- if(GXHitTestShape(hitShape, clickPt, &hitStats))
- break;
- }
-
- // If a shape was hit, track it
- if(shapeNum < 3)
- {
- gxPoint anchor, pt, lastPt = *clickPt;
-
- hitShape = gOpShapes[shapeNum];
-
- // Get the "anchor" point (shape 0)
- GXGetPoint(gOpShapes[0], &anchor);
-
- // Create a shape for saving the old position
- if(!gContRedraw)
- oldShape = GXCopyToShape(nil, hitShape);
-
- // Follow the drag around
- while(StillDown())
- {
- // Get the new mouse position and if it's different,
- // adjust the dragged shape
- GXGetViewPortMouse(gViewPort, &pt);
- if(pt.x != lastPt.x || pt.y != lastPt.y)
- {
- // Save old shape so we can erase and draw in rapid succession
- if(!gContRedraw)
- {
- GXCopyToShape(oldShape, hitShape);
-
- // If constraints are on, erase the dragger before.
- if(gKeepClosed)
- EraseAShape(gDragger.snake1);
- }
-
- // Move it
- p2_DragOpShape(hitShape, &pt, &anchor);
-
- if(gContRedraw)
- {
- // Reset pattern and draw it right now
- p2_ChangeLattice();
- OffToScreen();
- }
- else
- {
- // Erase and draw
- EraseAShape(oldShape);
- GXDrawShape(hitShape);
-
- // If constraints are on, draw the dragger too.
- if(gKeepClosed)
- GXDrawShape(gDragger.snake1);
- }
- }
- lastPt = pt;
- }
- if(!gContRedraw)
- {
- p2_ChangeLattice(); // Update the pattern
- GXDisposeShape(oldShape);
- }
- return true;
- }
- else // nothing hit
- return false;
- }
-
- // Moves the op shape as appropriate
- void p2_DragOpShape(gxShape dragShape, gxPoint *clickPt, gxPoint *anchor)
- {
- fixed xd = clickPt->x - anchor->x, yd = clickPt->y - anchor->y,
- lxd = labs(clickPt->x - anchor->x), lyd = labs(clickPt->y - anchor->y);
- gxPoint temp;
-
- // If the point is in bounds, just use it
- if(lxd < kMaxDistance && lyd < kMaxDistance &&
- (lyd > kMinDistance || lxd > kMinDistance) )
- {
- GXSetPoint(dragShape, clickPt);
- }
- else // Constrain it to the bounds
- {
- temp = *clickPt;
- if( lxd > kMaxDistance )
- temp.x = anchor->x + ( (xd < 0) ? -kMaxDistance : kMaxDistance);
- else if( lxd < kMinDistance )
- temp.x = anchor->x + ( (xd < 0) ? -kMinDistance : kMinDistance);
-
- if( lyd > kMaxDistance )
- temp.y = anchor->y + ( (yd < 0) ? -kMaxDistance : kMaxDistance);
- else if( lyd < kMinDistance )
- temp.y = anchor->y + ( (yd < 0) ? -kMinDistance : kMinDistance);
-
- GXSetPoint(dragShape, &temp);
- }
- }
-
- // Called either to set the default shapes when resetting the tile, or when
- // the symmetry has changed, to convert one lattice type to another.
- // Currently only resets to default
- void p2_RemakeOpShapes(Boolean useDefaults)
- {
- gxShape tempShape;
-
- if(true /* useDefaults */)
- {
- tempShape = MakeOpShape(roto2Op);
- GXMoveShape(tempShape, kStartingOffset, kStartingOffset);
- gOpShapes[0] = GXCopyToShape(nil, tempShape);
- GXMoveShape(tempShape, kStartingGridSize, 0);
- gOpShapes[1] = GXCopyToShape(nil, tempShape);
- GXMoveShape(tempShape, -kStartingGridSize, kStartingGridSize);
- gOpShapes[2] = tempShape;
- }
- }
-
- // Set the dragger to the default shape.
- void p2_SetDefaultDragger(gxShape snake)
- {
- long dragPoly[] = { 1, // number of contours
- 4, // number of points
- 0, kStartingGridSize,
- 0, 0,
- kStartingGridSize, 0,
- kStartingGridSize, kStartingGridSize };
-
-
- // make the starting drag shape
- GXSetPolygons(snake, (gxPolygons *) dragPoly);
- GXMoveShape(snake, kStartingOffset, kStartingOffset);
- }
-
- // Reset the pattern vectors according to the positions of the op shapes
- void p2_ChangeLattice(void)
- {
- gxPoint start, end1, end2;
-
- // Adjust points to define the true unit cell.
- GXGetPoint(gOpShapes[0], &start);
- GXGetPoint(gOpShapes[1], &end1);
- GXGetPoint(gOpShapes[2], &end2);
- gPattern.u.x = 2 *(end1.x - start.x);
- gPattern.u.y = 2 * (end1.y - start.y);
- gPattern.v.x = 2 * (end2.x - start.x);
- gPattern.v.y = 2 * (end2.y - start.y);
-
- // Now remake the pattern according to the new lattice and draw it offscreen
- RemakeTile();
- }
-
- // Repeat the tile geometry as necessary to build up the full unit cell
- void p2_BuildCellShape(gxShape snake)
- {
- gxShape tempShape;
- gxPoint origin, ctr;
-
- // Get the point to rotate around: center of the unit cell
- GXGetPoint(gOpShapes[0], &origin);
- ctr.x = origin.x + (gPattern.u.x + gPattern.v.x) / 2;
- ctr.y = origin.y + (gPattern.u.y + gPattern.v.y) / 2;
-
- // Copy the shape, rotate it, and add it back in
- tempShape = GXCopyToShape(nil, gTileShape);
- GXRotateShape(tempShape, ff(180), ctr.x, ctr.y);
- GXSetShapeParts(gTileShape, 0, gxSelectToEnd, tempShape, gxBreakLeftEdit);
- GXDisposeShape(tempShape);
- }
-